package yl.hs.bmipfull.service.salemanage.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import yl.hs.bmipfull.daos.production.IFinishProductWarehouseRecordDao;
import yl.hs.bmipfull.daos.production.IProductionTaskFertilizerDao;
import yl.hs.bmipfull.daos.salemanage.IContractControlInfoDao;
import yl.hs.bmipfull.daos.salemanage.ISaleOrderPlaceDao;
import yl.hs.bmipfull.daos.salemanage.ISaleOrderPlaceDetailDao;
import yl.hs.bmipfull.pojo.production.FinishProductInventoryEntity;
import yl.hs.bmipfull.pojo.production.FinishProductWarehouseRecordEntity;
import yl.hs.bmipfull.pojo.salemanage.SaleOrderPlaceDetailEntity;
import yl.hs.bmipfull.pojo.salemanage.SaleOrderPlaceEntity;
import yl.hs.bmipfull.service.finance.IContractAccountService;
import yl.hs.bmipfull.service.laboratory.IProductInfoService;
import yl.hs.bmipfull.service.production.IFinishProductInventoryService;
import yl.hs.bmipfull.service.production.IFinishProductWarehouseRecordService;
import yl.hs.bmipfull.service.salemanage.ISaleOrderPlaceService;
import yl.hs.bmipfull.utils.DataState;
import yl.hs.bmipfull.utils.HsApp;
import yl.hs.bmipfull.utils.Tl;
import yl.hs.bmipfull.utils.datastate.ActionType;
import yl.hs.bmipfull.viewmodels.PageQuery;
import yl.hs.bmipfull.viewmodels.PageResult;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 作用:  下单表服务层接口实现<br/>
 * 创建时间: 2023年06月25日 10时36分42秒 <br/>
 *
 * @author 吴高丰
 */
@Service
public class SaleOrderPlaceServiceImpl extends SaleBaseService implements ISaleOrderPlaceService {

    @Autowired
    ISaleOrderPlaceDao dao;
    @Autowired
    ISaleOrderPlaceDetailDao detailDao;
    @Autowired
    IFinishProductWarehouseRecordService finishProductWarehouseRecordService;
    @Autowired
    IContractAccountService contractAccountService;
    @Autowired
    IContractControlInfoDao contractControlInfoDao;
    @Autowired
    IFinishProductInventoryService inventoryService;
    @Autowired
    IProductInfoService infoService;
    @Autowired
    IFinishProductWarehouseRecordDao recordDao;
    @Autowired
    IProductionTaskFertilizerDao taskFertilizerDao;

    @Override
    public List<Object> queryList(PageQuery pageQuery) throws Exception {
        pageQuery.checkSortSides(SaleOrderPlaceEntity.class);
        var data = dao.queryPage(pageQuery.getQuery());
        List<Object> list = new ArrayList<>();
        for (SaleOrderPlaceEntity item : data) {
            var ss = item.toMap();
            var detail = detailDao.querySalePlaceSn(item.getSn());
            ss.put("detail", detail);
            list.add(ss);
        }
        return list;
    }

    @Override
    public PageResult<Object> queryPage(PageQuery pageQuery, int rowNum, int page) throws Exception {
        var user = HsApp.getCurrent();
        pageQuery.checkSortSides(SaleOrderPlaceEntity.class);
        pageQuery.getQuery().put("querySkip", (page - 1) * rowNum);
        pageQuery.getQuery().put("pageSize", rowNum);
        pageQuery.getQuery().put("sortKey", String.join(",", pageQuery.getSortSides()));
        if(user!=null){
            pageQuery.getQuery().put("types", user.getType()==null?0:user.getType());
        }
        PageResult<Object> result = new PageResult(rowNum);
        result.setRecords(dao.queryCountByCondition(pageQuery.getQuery()));
        result.setPage(page);
        var data = dao.queryPage(pageQuery.getQuery());
        List<Object> list = new ArrayList<>();
        for (SaleOrderPlaceEntity item : data) {
            var ss = item.toMap();
            var detail = detailDao.querySalePlaceSn(item.getSn());
            ss.put("detail", detail);
            list.add(ss);
        }
        result.setData(list);
        return result;
    }

    @Override
    public PageResult<Object> queryPageGD(PageQuery pageQuery, int rowNum, int page) throws Exception {
        pageQuery.checkSortSides(SaleOrderPlaceEntity.class);
        pageQuery.getQuery().put("querySkip", (page - 1) * rowNum);
        pageQuery.getQuery().put("pageSize", rowNum);
        pageQuery.getQuery().put("sortKey", String.join(",", pageQuery.getSortSides()));
        var contractSNList = getConstructionContractSN();
        pageQuery.getQuery().put("contractSNList", contractSNList);
        PageResult<Object> result = new PageResult(rowNum);
        result.setRecords(dao.queryCountByCondition(pageQuery.getQuery()));
        result.setPage(page);
        var data = dao.queryPage(pageQuery.getQuery());
        List<Object> list = new ArrayList<>();
        for (SaleOrderPlaceEntity item : data) {
            var ss = item.toMap();
            var detail = detailDao.querySalePlaceSn(item.getSn());
            ss.put("detail", detail);
            list.add(ss);
        }
        result.setData(list);
        return result;
    }

    @Override
    public Map<String, Object> queryPlace() throws Exception {
        var contractSNList = getConstructionContractSN();
        var data = dao.queryByState(contractSNList);
        Map<String, Object> map = new HashMap<>();
        int examinecc = 0;
        BigDecimal examineWeight = BigDecimal.valueOf(0);
        int deliverycc = 0;
        BigDecimal deliveryWeight = BigDecimal.valueOf(0);
        for (SaleOrderPlaceEntity item : data) {
            var weight = detailDao.querySalePlaceSn(item.getSn()).stream().map(SaleOrderPlaceDetailEntity::getQuantity).reduce(BigDecimal::add).get();
            if (item.getState() < 3) {
                examinecc = examinecc + 1;
                examineWeight = examineWeight.add(weight);
            } else {
                deliverycc = deliverycc + 1;
                deliveryWeight = deliveryWeight.add(weight);
            }
        }
        map.put("待审核车次", examinecc);
        map.put("待审核重量", examineWeight);
        map.put("待提货车次", deliverycc);
        map.put("待提货重量", deliveryWeight);
        return map;
    }


    @Override
    public SaleOrderPlaceEntity findBySn(String sn) {
        return dao.findBySN(sn);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer savesale_order_place(Map<String, Object> model, String sn) throws Exception {
        //提货单状态，1 待业务员审核，2 待销售审核，3 待提货，4已出库，5已完成
        Integer result = 0;
        SaleOrderPlaceEntity entity = null;
        if (Tl.isEmpty(sn)) {
            //执行保存
            entity = new SaleOrderPlaceEntity();
            Tl.getChangeLog(entity, model);
            entity.setPYFieldValue();
            entity.setSn(queryNewSN(SaleOrderPlaceEntity.class));
            var detail = (List<Map<String, Object>>) model.get("detail");
            var money = new BigDecimal(0);
            for (Map<String, Object> map : detail) {
                money = money.add(new BigDecimal(map.get("money") == null ? "0" : map.get("money").toString()));
            }
            var zt = checkControl(entity.getContractSN(), "", null, money);
            if (zt) {
                return -1;
            }
            for (var item : detail) {
                var task = taskFertilizerDao.queryByContractSN(entity.getContractSN(), entity.getPlaceOrderTime(), item.get("productSN").toString());
                if (task.size() > 0) {
                    //return 1;
                } else {
                    var inventory = inventoryService.findByProductSN(item.get("productSN").toString(), item.get("packageName").toString(), item.get("packageSn").toString());
                    if (inventory.size() > 0) {
                        var info = infoService.findBySn(item.get("productSN").toString());
                        var saledetail = detailDao.queryListByState(item.get("productSN").toString());
                        var wei = recordDao.queryByTypeAndProduct(2, item.get("productSN").toString(), 1);
                        if (info != null) {
                            if (((inventory.stream().map(FinishProductInventoryEntity::getWeight).reduce(BigDecimal::add).get()).subtract(saledetail).subtract(wei)).compareTo(new BigDecimal(item.get("quantity").toString())) < 0) {
                                return -2;
                            }
                        }
                        //if (((inventory.stream().map(FinishProductInventoryEntity::getWeight).reduce(BigDecimal::add).get()).subtract(wei).subtract(saledetail)).compareTo(new BigDecimal(item.get("quantity").toString())) < 0) {
                        //return -2;
                        //}
                    } else {
                        return -2;
                    }
                }
            }
            result = dao.insertNew(entity);
            for (var item : detail) {
                SaleOrderPlaceDetailEntity detailEntity = new SaleOrderPlaceDetailEntity();
                detailEntity.setSn(queryNewSN(SaleOrderPlaceDetailEntity.class));
                detailEntity.setOrderPlaceSn(entity.getSn());
                detailEntity.setPackageName(item.get("packageName").toString());
                detailEntity.setPackageSn(item.get("packageSn").toString());
                detailEntity.setPackageUnit(item.get("packageUnit").toString());
                detailEntity.setPackageWeight(new BigDecimal(item.get("packageWeight").toString()));
                detailEntity.setOrderQuantity(new BigDecimal(item.get("orderQuantity") == null ? "0" : item.get("orderQuantity").toString()));
                detailEntity.setProductName(item.get("productName").toString());
                detailEntity.setProductCateName(item.get("productCateName").toString());
                detailEntity.setQuantity(new BigDecimal(item.get("quantity").toString()));
                detailEntity.setProductCateSn(item.get("productCateSn").toString());
                detailEntity.setProductSN(item.get("productSN").toString());
                detailEntity.setProductSpec(item.get("productSpec").toString());
                detailEntity.setRemark(item.get("remark") == null ? "" : item.get("remark").toString());
                detailEntity.setState(Short.valueOf(item.get("state").toString()));
                detailEntity.setPrice(item.get("price") == null ? BigDecimal.valueOf(0) : new BigDecimal(item.get("price").toString()));
                detailEntity.setMoney(item.get("money") == null ? BigDecimal.valueOf(0) : new BigDecimal(item.get("money").toString()));
                detailDao.insertNew(detailEntity);
            }
            if (result > 0) {
                writeLog(ActionType.CREATE, entity.getSn(), "插入下单表信息", Tl.toJson(entity), SaleOrderPlaceEntity.class);
            }

        } else
        {
            //执行修改
            entity = findBySn(sn);
            var state = entity.getState();
            Tl.getChangeLog(entity, model);
            entity.setPYFieldValue();
            if(entity.getMatching()==null){
                entity.setMatching(0);
            }
            var detail = (List<Map<String, Object>>) model.get("detail");
            var money = new BigDecimal(0);
            for (Map<String, Object> map : detail) {
                money = money.add(new BigDecimal(map.get("money") == null ? "0" : map.get("money").toString()));
            }
            if (state > entity.getState()) {
                return -3;
            }
            if (model.get("isShip") == null) {
                if (state.equals(entity.getState())) {
                    return dao.updateRemark(entity.getSn(), entity.getRemark());
                }
            }
            if (entity.getState() == 2 && state == 1) {
                var zt = checkControl(entity.getContractSN(), "", null, money);
                if (zt) {
                    return -1;
                }
            }
            if ((entity.getState() == 2 || entity.getState() == 3) && !state.equals(entity.getState()) && entity.getMatching() != 1) {
                for (var item : detail) {
                    var inventory = inventoryService.findByProductSN(item.get("productSN").toString(), item.get("packageName").toString(), item.get("packageSn").toString());
                    if (inventory.size() > 0) {
                        var info = infoService.findBySn(item.get("productSN").toString());
                        var saledetail = detailDao.queryListByState(item.get("productSN").toString());
                        var wei = recordDao.queryByTypeAndProduct(2, item.get("productSN").toString(), 1);
                        if (info != null) {
                            if (((inventory.stream().map(FinishProductInventoryEntity::getWeight).reduce(BigDecimal::add).get()).subtract(saledetail).subtract(wei)).compareTo(new BigDecimal(item.get("quantity").toString())) < 0) {
                                return -2;
                            }
                        }
                        //if (((inventory.stream().map(FinishProductInventoryEntity::getWeight).reduce(BigDecimal::add).get()).subtract(saledetail).subtract(wei)).compareTo(new BigDecimal(item.get("quantity").toString())) < 0) {
                        //return -2;
                        //}
                    } else {
                        return -2;
                    }
                }
            }
            if (entity.getState() == 4 && entity.getMatching() != 1) {
                for (var item : detail) {
                    var inventory = inventoryService.findByProductSNAndWareHouseSN(item.get("productSN").toString(), item.get("packageName").toString(), item.get("packageSn").toString(), item.get("wareHouseSN").toString());
                    if (inventory.size() > 0 && entity.getMatching() != 1) {
                        var info = infoService.findBySn(item.get("productSN").toString());
                        if (info != null) {
                            if ((inventory.stream().map(FinishProductInventoryEntity::getWeight).reduce(BigDecimal::add).get()).compareTo(new BigDecimal(item.get("quantity").toString())) < 0) {
                                return -2;
                            }
                        }
                        //if ((inventory.stream().map(FinishProductInventoryEntity::getWeight).reduce(BigDecimal::add).get()).compareTo(new BigDecimal(item.get("quantity").toString())) < 0) {
                        ///return -2;
                        //}
                    } else {
                        return -2;
                    }
                }
            }
            detailDao.deleteByPlaceSn(sn);
            result = dao.update(entity);
            for (var item : detail) {
                SaleOrderPlaceDetailEntity detailEntity = new SaleOrderPlaceDetailEntity();
                detailEntity.setSn(queryNewSN(SaleOrderPlaceDetailEntity.class));
                detailEntity.setOrderPlaceSn(entity.getSn());
                detailEntity.setPackageName(item.get("packageName").toString());
                detailEntity.setPackageSn(item.get("packageSn").toString());
                detailEntity.setPackageUnit(item.get("packageUnit").toString());
                detailEntity.setPackageWeight(new BigDecimal(item.get("packageWeight").toString()));
                detailEntity.setProductName(item.get("productName").toString());
                detailEntity.setProductCateName(item.get("productCateName").toString());
                detailEntity.setQuantity(new BigDecimal(item.get("quantity").toString()));
                detailEntity.setOrderQuantity(new BigDecimal(item.get("orderQuantity") == null ? "0" : item.get("orderQuantity").toString()));
                detailEntity.setProductCateSn(item.get("productCateSn").toString());
                detailEntity.setProductSN(item.get("productSN").toString());
                detailEntity.setProductSpec(item.get("productSpec").toString());
                detailEntity.setRemark(item.get("remark") == null ? "" : item.get("remark").toString());
                detailEntity.setState(Short.valueOf(item.get("state").toString()));
                detailEntity.setWareHouseName(item.get("wareHouseName") == null ? "" : item.get("wareHouseName").toString());
                detailEntity.setWareHouseSN(item.get("wareHouseSN") == null ? "" : item.get("wareHouseSN").toString());
                detailEntity.setOutboundName(item.get("outboundName") == null ? "" : item.get("outboundName").toString());
                detailEntity.setOutboundSN(item.get("outboundSN") == null ? "" : item.get("outboundSN").toString());
                detailEntity.setPrice(item.get("price") == null ? BigDecimal.valueOf(0) : new BigDecimal(item.get("price").toString()));
                detailEntity.setMoney(item.get("money") == null ? BigDecimal.valueOf(0) : new BigDecimal(item.get("money").toString()));
                if (item.get("outboundDate") == null) {
                    detailEntity.setOutboundDate(null);
                } else {
                    var dates = item.get("outboundDate").toString();
                    SimpleDateFormat ss = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    Date time = ss.parse(dates);
                    detailEntity.setOutboundDate(time);
                }
                detailDao.insertNew(detailEntity);
                if (entity.getState() == 4 && state == 3) {
                    FinishProductWarehouseRecordEntity ss = new FinishProductWarehouseRecordEntity();
                    ss.setSn(queryNewSN(FinishProductWarehouseRecordEntity.class));
                    ss.setProductCateSN(detailEntity.getProductCateSn());
                    ss.setProductSN(detailEntity.getProductSN());
                    ss.setProductCateName(detailEntity.getProductCateName());
                    ss.setProductName(detailEntity.getProductName());
                    ss.setProductSpec(detailEntity.getProductSpec());
                    ss.setPackageName(detailEntity.getPackageName());
                    ss.setPackageSN(detailEntity.getPackageSn());
                    ss.setProductConfigName("");
                    ss.setProductConfigSN("");
                    ss.setWeight(detailEntity.getQuantity());
                    ss.setQuantity((detailEntity.getQuantity().multiply(BigDecimal.valueOf(1000))).divide(detailEntity.getPackageWeight()));
                    ss.setInTime(new Date());
                    ss.setWareHouseName(detailEntity.getWareHouseName());
                    ss.setWareHouseSN(detailEntity.getWareHouseSN());
                    if (entity.getMatching() == 1) {
                        ss.setRemark("对装出货");
                    } else {
                        ss.setRemark("");
                    }
                    ss.setPbName("");
                    ss.setTaskSN("");
                    ss.setState((short) 2);
                    ss.setType((short) 2);
                    ss.setRkState(1);
                    ss.setTeams(detailEntity.getOutboundName());
                    ss.setTruckPlate(entity.getTruckPlate());
                    finishProductWarehouseRecordService.insert(ss);
                }
            }
            if (result > 0) {
                writeLog(ActionType.UPDATE, sn, "更新下单表信息", Tl.toJson(entity), SaleOrderPlaceEntity.class);
            }
        }

        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer delete(String sn) {
        Integer result = dao.changeStateBySN(sn, DataState.DELETED.code);
        if (result > 0) {
            writeLogDeleteSn(ActionType.DELETE, sn, SaleOrderPlaceEntity.class);
        }
        return result;
    }

    @Override
    public List<SaleOrderPlaceDetailEntity> queryDetailBySn(String sn) {
        return detailDao.querySalePlaceSn(sn);
    }

    @Override
    public SaleOrderPlaceEntity findByTruckPlate(String truckplate, int state) {
        return dao.findByTruckPlate(truckplate, state);
    }

    @Override
    public Object querylistByState(String truckplate) {
        var data = dao.querylistByState(truckplate);
        if (data.stream().filter(s -> s.getState() == 3).toList().size() > 0) {
            for (SaleOrderPlaceEntity item : data) {
                item.setChecks(1);
                item.setCheckTime(new Date());
                dao.update(item);
            }
            return detailDao.querySalePlaceSn(data.get(0).getSn());
        } else if (data.stream().filter(s -> s.getState() < 3).toList().size() > 0) {
            for (SaleOrderPlaceEntity item : data) {
                item.setChecks(1);
                item.setCheckTime(new Date());
                dao.update(item);
            }
            return 2;
        } else {
            return 3;
        }
    }

    private boolean checkControl(String contractSn, String productionTags, String productCateSn, BigDecimal je) throws Exception {
        var controlFlag = false;
        var ctlList = contractControlInfoDao.queryByContractSn(contractSn);
        if (ctlList.size() > 0) {

            var message = "";
            for (var control : ctlList) {
                var min = control.getStartTime();
                switch (control.getControlType()) {
                    case (short) 1://天数控制
                        Calendar dt = Calendar.getInstance();
                        dt.setTime(min);
                        dt.add(Calendar.DATE, (int) control.getDisabValue());
                        if ((new Date()).compareTo(dt.getTime()) > 0) {
                            controlFlag = true;
                            message = "已超过合同发货天数控制，禁止发货";
                        }
                        break;
                    case (short) 2:
                        if (!control.isControlWay()) {
                        } else {
                            PageQuery model = new PageQuery();
                            Map<String, Object> map = new HashMap<>();
                            map.put("productCateSn", productCateSn);
                            map.put("sn", control.getContractSN());
                            model.setQuery(map);
                            var ss = contractAccountService.queryHfList(model, 1, 15);
                            if (ss != null && ss.getData() != null && ss.getData().size() > 0) {
                                var money = ss.getData().get(0).getContractBalance();
                                if (money.compareTo(je) < 0) {
                                    controlFlag = true;
                                    message = "已超过合同发货金额控制，禁止发货";
                                }
                            }
                        }
                        break;
                    case (short) 3:
                        break;
                }
            }
        }
        return controlFlag;
    }
}